package com.fastwire.carriere.controller.impl;

import java.util.Date;
import java.util.List;
import java.util.Set;

import com.fastwire.carriere.common.Messages;
import com.fastwire.carriere.common.constant.UserConstants;
import com.fastwire.carriere.common.exception.ResourceException;
import com.fastwire.carriere.common.util.DateUtil;
import com.fastwire.carriere.common.util.StringUtil;
import com.fastwire.carriere.controller.UserController;
import com.fastwire.carriere.dao.DAOException;
import com.fastwire.carriere.dao.DAOFactory;
import com.fastwire.carriere.dao.UserDao;
import com.fastwire.carriere.dao.UserSessionDao;
import com.fastwire.carriere.user.entity.Permission;
import com.fastwire.carriere.user.entity.User;
import com.fastwire.carriere.user.entity.UserGroup;
import com.fastwire.carriere.user.entity.UserSession;
import com.fastwire.carriere.user.vo.PermissionVo;
import com.fastwire.carriere.user.vo.SessionVo;
import com.fastwire.carriere.user.vo.UserGroupVo;
import com.fastwire.carriere.user.vo.UserVo;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

public class UserControllerImpl implements UserController {

	UserSessionDao userSessionDao = DAOFactory.getInstance()
			.getUserSessionDao();

	@Override
	public SessionVo login(UserVo inputUser) throws ResourceException,
			DAOException {

		UserDao userDao = DAOFactory.getInstance().getUserDao();

		User currUser = userDao.getUserbyName(inputUser.getName());

		if (currUser == null) {
			throw new ResourceException(Messages.getString(
					"message.common.user.usernotexist.exception",
					new String[] { inputUser.getName() }));

		}

		if (!currUser.getPassword().equals(inputUser.getPassword())) {

			throw new ResourceException(
					Messages.getString("message.common.user.passwordincorrect.exception"));

		}

		List<PermissionVo> permissionVos = Lists.newArrayList();

		for (Permission permission : currUser.getUserGroup().getPermissions()) {
			permissionVos.add(new PermissionVo(permission));
		}

		UserSession session = new UserSession(currUser.getName(), permissionVos);

		userSessionDao.saveOrUpdate(session);
		return new SessionVo(session);
	}

	/**
	 * Creates the user group.
	 * 
	 * @param userGroupVo
	 *            the user group vo
	 * @throws ResourceException
	 *             the resource exception
	 * @throws DAOException
	 *             the dAO exception
	 */
	@Override
	public void createUserGroup(UserGroupVo userGroupVo)
			throws ResourceException, DAOException {

		UserDao userDao = DAOFactory.getInstance().getUserDao();

		UserGroup userGroup = userDao.getUserGroupbyName(userGroupVo.getName());

		if (userGroup != null) {
			throw new ResourceException(Messages.getString(
					"message.common.user.usergroupadiexist.exception",
					new String[] { userGroupVo.getName() }));
		}

		UserGroup newUserGroup = new UserGroup();
		newUserGroup.setName(userGroupVo.getName());
		newUserGroup.setDescription(userGroupVo.getDescription());
		Set<Permission> permissions = Sets.newHashSet();
		if (userGroupVo.getPermissions() != null) {

			for (PermissionVo permissionVo : userGroupVo.getPermissions()) {
				Permission permission = new Permission();
				permission.setName(permissionVo.getName());
				permission.setAction(permissionVo.getAction());
				permissions.add(permission);
			}
		}
		newUserGroup.setPermissions(permissions);

		userDao.saveOrUpdate(newUserGroup);

	}

	/**
	 * Edits the user group.
	 * 
	 * @param userGroupVo
	 *            the user group vo
	 * @throws ResourceException
	 *             the resource exception
	 * @throws DAOException
	 *             the dAO exception
	 */
	@Override
	public void editUserGroup(UserGroupVo userGroupVo)
			throws ResourceException, DAOException {

		UserDao userDao = DAOFactory.getInstance().getUserDao();

		UserGroup userGroup = userDao.getUserGroupbyId(Long
				.parseLong(userGroupVo.getOid()));

		if (userGroup == null) {
			throw new ResourceException(Messages.getString(
					"message.common.user.usergroupnotexist.exception",
					new String[] { userGroupVo.getOid() }));
		}

		userGroup.setDescription(userGroupVo.getDescription());
		Set<Permission> permissions = Sets.newHashSet();
		if (userGroupVo.getPermissions() != null) {

			for (PermissionVo permissionVo : userGroupVo.getPermissions()) {
				Permission permission = new Permission();
				permission.setName(permissionVo.getName());
				permission.setAction(permissionVo.getAction());
				permissions.add(permission);
			}
		}
		userGroup.setPermissions(permissions);

		userDao.saveOrUpdate(userGroup);

	}

	/**
	 * Creates the user.
	 * 
	 * @param userVo
	 *            the user vo
	 * @throws ResourceException
	 *             the resource exception
	 * @throws DAOException
	 *             the dAO exception
	 */
	@Override
	public void createUser(UserVo userVo) throws ResourceException,
			DAOException {

		UserDao userDao = DAOFactory.getInstance().getUserDao();

		User user = userDao.getUserbyName(userVo.getName());

		if (user != null) {
			throw new ResourceException(Messages.getString(
					"message.common.user.useradiexist.exception",
					new String[] { userVo.getName() }));
		}

		UserGroup userGroup = userDao.getUserGroupbyName(userVo.getUserGroup());

		User newUser = new User(userVo);
		newUser.setUserGroup(userGroup);

		userDao.saveOrUpdate(newUser);

	}

	/**
	 * Edits the user.
	 * 
	 * @param userVo
	 *            the user vo
	 * @throws ResourceException
	 *             the resource exception
	 * @throws DAOException
	 *             the dAO exception
	 */
	@Override
	public void editUser(UserVo userVo) throws ResourceException, DAOException {

		UserDao userDao = DAOFactory.getInstance().getUserDao();

		User user = userDao.getUserbyName(userVo.getName());

		if (user == null) {
			throw new ResourceException(Messages.getString(
					"message.common.user.usernotexist.exception",
					new String[] { userVo.getName() }));
		}

		UserGroup userGroup = userDao.getUserGroupbyName(userVo.getUserGroup());

		user.setEmail(userVo.getEmail());
		//Change password only if it is not null or empty.
		//Otherwise password will become NULL
		if(!StringUtil.isEmptyString(userVo.getPassword())) {
			user.setPassword(userVo.getPassword());
        }
		user.setUserGroup(userGroup);
		user.setUpdateDate(DateUtil.getDate());

		userDao.saveOrUpdate(user);

	}

	/**
	 * Search user.
	 * 
	 * @param searchVo
	 *            the search vo
	 * @return the list
	 * @throws ResourceException
	 *             the resource exception
	 * @throws DAOException
	 *             the dAO exception
	 */
	@Override
	public List<UserVo> searchUser(UserVo searchVo, String loginUser)
			throws ResourceException, DAOException {

		UserDao userDao = DAOFactory.getInstance().getUserDao();

		User loginuser = userDao.getUserbyName(loginUser);

		/*
		 * if (!UserConstants.GROUP_SUPER.equals(loginuser.getUserGroup()
		 * .getName())) {
		 * searchVo.setUserGroup(loginuser.getUserGroup().getName()); }
		 */

		List<User> users = userDao.getUsersbySearchCriteria(searchVo);

		List<UserVo> userVos = Lists.newArrayList();

		for (User user : users) {
			userVos.add(new UserVo(user));
		}

		return userVos;

	}

	/**
	 * Search user group.
	 * 
	 * @param searchVo
	 *            the search vo
	 * @return the list
	 * @throws ResourceException
	 *             the resource exception
	 * @throws DAOException
	 *             the dAO exception
	 */
	@Override
	public List<UserGroupVo> searchUserGroup(UserGroupVo searchVo)
			throws ResourceException, DAOException {

		UserDao userDao = DAOFactory.getInstance().getUserDao();

		List<UserGroup> userGroups = userDao
				.getUserGroupsbySearchCriteria(searchVo);

		List<UserGroupVo> userGroupVos = Lists.newArrayList();

		for (UserGroup userGroup : userGroups) {
			userGroupVos.add(new UserGroupVo(userGroup));
		}

		return userGroupVos;

	}

	/**
	 * Delete user.
	 * 
	 * @param objId
	 *            the obj id
	 * @throws DAOException
	 *             the dAO exception
	 */
	@Override
	public void deleteUser(long objId) throws DAOException {

		UserDao userDao = DAOFactory.getInstance().getUserDao();

		userDao.deleteUserbyId(objId);
	}

	/**
	 * Delete user group.
	 * 
	 * @param objId
	 *            the obj id
	 * @throws DAOException
	 *             the dAO exception
	 * @throws ResourceException
	 */
	@Override
	public void deleteUserGroup(long objId) throws DAOException,
			ResourceException {

		UserDao userDao = DAOFactory.getInstance().getUserDao();
		UserGroup userGroup = userDao.getUserGroupbyId(objId);

		if (userGroup != null) {
			List<User> users = userDao.getUsersbyUserGroup(userGroup);
			if (users != null && users.size() > 0) {
				throw new ResourceException(Messages.getString(
						"message.common.user.usergroupdelete.exception",
						new String[] { String.valueOf(userGroup.getName()) }));
			}
		}

		userDao.deleteUserGroupbyId(objId);
	}

	@Override
	public void logout(SessionVo sessionVo) throws ResourceException,
			DAOException {
		UserSession userSession = userSessionDao.getUserSession(
				sessionVo.getUserName(),
				Long.parseLong(sessionVo.getSessionId()));

		if (userSession == null
				|| !UserConstants.STATUS_ACTIVE.equals(userSession.getStatus())) {

			throw new ResourceException(
					Messages.getString("message.usersession.inactive.exception"));

		}

		userSession.setStatus(UserConstants.STATUS_INACTIVE);
		userSession.setLogoutDate(new Date());
		userSessionDao.saveOrUpdate(userSession);

	}

}
